#include "windows/sims.h"
#include "windows/addstudent.h"
#include "ui_sims.h"

#include <algorithm>
#include <fstream>
#include <sstream>

#include <QLabel>
#include <QFileDialog>
#include <QMessageBox>

#include <QDragEnterEvent>
#include <QUrl>
#include <QMimeData>
#include <QTextCodec>
#include <QAxObject>

#include <QtCharts>

SIMS::SIMS(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::SIMS)
{
    ui->setupUi(this);

    // 状态栏初始化
    QLabel *statusBarInit = new QLabel("欢迎使用SIMS  ", this);
    ui->statusbar->addPermanentWidget(statusBarInit, 0);

    // 标签页初使化
    ui->tabWidget->clear();

    // 使能拖动触发
    setAcceptDrops(true);

    // 设置状态栏统计学生数量
    labStudNum = new QLabel();
    labStudNum->setText(QString("学生数量：0"));
    labStudNum->setMinimumWidth(100);
    ui->statusbar->addWidget(labStudNum);
}

SIMS::~SIMS()
{
    delete ui;
    delete &tableList;
    delete &StudentLists;
    delete &StuParameters;
}

/**
 * @brief 读取TXT
 * @param _filePath
 */
void SIMS::readTXT(const string _filePath)
{
    string tempLineData; // 每一行读取到的数据
    string point;        // 每一行中的元素

    StudentParameterType *stuParameter = new StudentParameterType(); // 学生属性
    StudentListType *studentList = new StudentListType();            // 学生列表

    std::ifstream infile(_filePath);    // 文件流
    getline(infile, tempLineData);      // 先读取第一行表头
    std::stringstream ss(tempLineData); // 整行转为字符串流
    while (ss >> point)
    {
        if (point == "总分" || point == "排名" || point == "优良等级")
            continue;
        stuParameter->push_back(point); // 记录表头元素
    }
    stuParameter->push_back("总分");
    stuParameter->push_back("排名");
    stuParameter->push_back("优良等级");
    StuParameters.push_back(stuParameter);

    // 绘制表头
    tableList.back()->setColumnCount(stuParameter->size()); // 设置表格列数
    QStringList list;
    for (auto &p : *stuParameter)
    {
        list << QString::fromStdString(p);
    }
    tableList.back()->setHorizontalHeaderLabels(list);

    // 表格数据处理和绘制
    int currentRow = 0;                   // 当前行
    int currentColumn = 0;                // 当前列
    while (getline(infile, tempLineData)) // 先读取整行直到文件末尾
    {
        std::stringstream sss(tempLineData);
        StudentsClassDef *student = new StudentsClassDef();
        for (auto &p : *stuParameter)
        {
            if (p == "总分" || p == "排名" || p == "优良等级")
                break;
            sss >> point;
            tableList.back()->setItem(currentRow, currentColumn, new QTableWidgetItem(QString::fromStdString(point)));
            tableList.back()->item(currentRow, currentColumn++)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
            student->set_Parameter(p, point);
        }
        currentColumn = 0;
        currentRow++;
        student->set_totalScore();
        studentList->push_back(student);
    }
    tableList.back()->setRowCount(currentRow);

    currentColumn = tableList.back()->columnCount() - 3;

    // 计算学生总分、排名、优良等级并显示
    while (currentRow--)
    {
        int Column = currentColumn;
        (*studentList)[currentRow]->set_rank(studentList);
        (*studentList)[currentRow]->set_level(studentList->size());

        float totalScore = (*studentList)[currentRow]->totalScore;
        float rank = (*studentList)[currentRow]->rank;
        string level = (*studentList)[currentRow]->level;

        tableList.back()->setItem(currentRow, Column, new QTableWidgetItem(QString("%1").arg(totalScore)));
        tableList.back()->item(currentRow, Column++)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

        tableList.back()->setItem(currentRow, Column, new QTableWidgetItem(QString("%1").arg(rank)));
        tableList.back()->item(currentRow, Column++)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

        tableList.back()->setItem(currentRow, Column, new QTableWidgetItem(QString::fromStdString(level)));
        tableList.back()->item(currentRow, Column++)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    }

    // 记录当前表格学生数据
    StudentLists.push_back(studentList);

    setStatusNum(studentList->size());

    infile.close();
}

/**
 * @brief 读取Excel
 * @param filePath
 */
void SIMS::readExcel(const QString filePath)
{
    /************************excel表格预处理*************************/

    QAxObject *excel = new QAxObject("Excel.Application");                                                        // excel应用程序
    excel->dynamicCall("SetVisible(bool)", false);                                                                // true 表示操作文件时可见，false表示为不可见
    QAxObject *workbooks = excel->querySubObject("WorkBooks");                                                    // 所有excel文件
    QAxObject *workbook = workbooks->querySubObject("Open(Const QString &)", QDir::toNativeSeparators(filePath)); // 按照路径获取文件
    QAxObject *worksheet = workbook->querySubObject("Worksheets(int)", 1);                                        // 获取文件sheet页
    if (nullptr == worksheet)
    {
        qWarning() << filePath << "Sheet页不存在。";
        return;
    }
    QAxObject *usedrange = worksheet->querySubObject("UsedRange"); // 有数据的矩形区域

    // 获取行数
    QAxObject *rows = usedrange->querySubObject("Rows");
    int nRows = rows->property("Count").toInt() - 1;
    if (nRows <= 1)
    {
        qWarning() << "无数据，跳过该文件";
        return;
    }

    // 获取列数
    QAxObject *columns = usedrange->querySubObject("Columns");
    int nColumns = columns->property("Count").toInt();

    // 读取整个表格
    QAxObject *usedRange = worksheet->querySubObject("UsedRange");

    /************************获取excel数据并呈现在QTable上*************************/
    StudentParameterType *stuParameter = new StudentParameterType(); // 学生属性
    StudentListType *studentList = new StudentListType();            // 学生列表
    QVariant var = usedRange->dynamicCall("Value");                  // 整个表格数据存储在var中
    tableList.back()->setRowCount(nRows);                            // 设置表格行数

    string point;          // 每一单元的值
    int currentRow = 0;    // 当前行
    int currentColumn = 0; // 当前列
    foreach (QVariant varRow, var.toList())
    { // 把var每一行数据赋值给varRow

        if (currentRow == 0)
        {
            // 处理表头
            foreach (QVariant item, varRow.toList())
            {
                point = item.toString().toStdString();
                if (point == "总分" || point == "排名" || point == "优良等级")
                    continue;
                stuParameter->push_back(point); // 记录表头元素
                currentColumn++;
            }
            stuParameter->push_back("总分");
            stuParameter->push_back("排名");
            stuParameter->push_back("优良等级");
            StuParameters.push_back(stuParameter); // 参数表添加到参数列表
            currentRow++;

            // 绘制表头
            tableList.back()->setColumnCount(stuParameter->size()); // 设置表格列数
            QStringList list;
            for (auto &p : *stuParameter)
            {
                list << QString::fromStdString(p);
            }
            tableList.back()->setHorizontalHeaderLabels(list);
        }
        else
        { // 处理表格主体
            currentColumn = 0;
            StudentsClassDef *student = new StudentsClassDef();
            foreach (QVariant item, varRow.toList())
            {
                string p = (*stuParameter)[currentColumn];
                if (p == "总分" || p == "排名" || p == "优良等级")
                    continue;
                point = item.toString().toStdString();

                tableList.back()->setItem(currentRow - 1, currentColumn, new QTableWidgetItem(QString::fromStdString(point)));
                tableList.back()->item(currentRow - 1, currentColumn++)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
                student->set_Parameter(p, point);
            }
            student->set_totalScore();
            studentList->push_back(student);

            currentRow++;
        }
    }

    // 计算学生总分、排名、优良等级并显示
    currentColumn = tableList.back()->columnCount() - 3;
    currentRow = nRows;
    while (currentRow--)
    {
        int Column = currentColumn;
        (*studentList)[currentRow]->set_rank(studentList);
        (*studentList)[currentRow]->set_level(studentList->size());

        float totalScore = (*studentList)[currentRow]->totalScore;
        float rank = (*studentList)[currentRow]->rank;
        string level = (*studentList)[currentRow]->level;

        tableList.back()->setItem(currentRow, Column, new QTableWidgetItem(QString("%1").arg(totalScore)));
        tableList.back()->item(currentRow, Column++)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

        tableList.back()->setItem(currentRow, Column, new QTableWidgetItem(QString("%1").arg(rank)));
        tableList.back()->item(currentRow, Column++)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

        tableList.back()->setItem(currentRow, Column, new QTableWidgetItem(QString::fromStdString(level)));
        tableList.back()->item(currentRow, Column++)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    }

    // 记录当前表格学生数据
    StudentLists.push_back(studentList);

    // 状态栏学生数量更新
    setStatusNum(studentList->size());

    /***********************关闭excel文件**************************/
    workbook->dynamicCall("Close()");
    excel->dynamicCall("Quit()");
    if (excel)
    {
        delete excel;
        excel = NULL;
    }
}

/**
 * @brief Unicode编码格式转本地编码格式（解决windows中文路径文件无法读取问题）
 * @param _filePath
 * @return
 */
std::string SIMS::UnicodetoLocale(QString _filePath)
{
    QTextCodec *code = QTextCodec::codecForName("GB2312");
    std::string filePath = code->fromUnicode(_filePath).data();
    return filePath;
}

/**
 * @brief 设置状态栏学生数量
 * @param num
 */
void SIMS::setStatusNum(int num)
{
    labStudNum->setText(QString("学生数量：%1").arg(num));
}

/**
 * @brief 绘制各科及格率条形图
 */
void SIMS::drawPassRateCharts()
{
    vector<CourseStructDef *> courses;
    int i = ui->tabWidget->currentIndex();
    courses = StudentLists[i]->back()->coursescores;

    QList<QString> qcourses;
    // QBarSet 类表示条形图中的一组条形
    QBarSet *set = new QBarSet("");
    for (auto c : courses)
    {
        qcourses << QString::fromStdString(c->name);

        // 计算每一科及格率
        *set << get_PassRate(StudentLists[i], c->name);
    }

    // QBarSeries 类将一系列数据显示为按类别分组的垂直条。
    QBarSeries *series = new QBarSeries();
    series->append(set);

    // QChart 类管理图表系列(series)、图例(legends)和轴(axes)。
    QChart *chart = ui->qChartLeft->chart();              // 获取QChartView自带的chart
    chart->addSeries(series);                             // 将创建好的条形图series添加进chart中
    chart->setTitle("各科及格率");                        // 设置标题
    chart->setAnimationOptions(QChart::SeriesAnimations); // 设置图表变化时的动画效果

    // X轴分类，一般与QBarSet中添加的数据个数相同，如果少了则会显示不全,多了不影响，但是不能重复
    QStringList categories;
    for (auto c : qcourses)
    {
        categories << c;
    }

    // QBarCategoryAxis类向图表的轴添加类别。
    QBarCategoryAxis *axisX = new QBarCategoryAxis();
    axisX->setTitleText("科目"); // 设置X轴标题
    axisX->append(categories);
    chart->addAxis(axisX, Qt::AlignBottom); // 将X轴放在图表的底部
    series->attachAxis(axisX);              // 将axis指定的轴附着到series。

    QValueAxis *axisY = new QValueAxis(); // 创建Y轴
    axisY->setRange(0, 1);                // 设置Y轴范围
    axisY->setTitleText("及格率");        // 设置Y轴标题
    chart->addAxis(axisY, Qt::AlignLeft); // Y轴左对齐
    series->attachAxis(axisY);

    chart->legend()->setVisible(true);             // 设置图例是否可见（默认是可见的）
    chart->legend()->setAlignment(Qt::AlignRight); // 设置图例显示的位置

    ui->qChartLeft->setRenderHint(QPainter::Antialiasing); // 设置抗锯齿（不过在条形图中不设置也没关系）
}

/**
 * @brief 绘制各科各分数层百分比条形图
 */
void SIMS::drawScoreRateCharts()
{
    vector<CourseStructDef *> courses;
    int i = ui->tabWidget->currentIndex();
    courses = StudentLists[i]->back()->coursescores;

    QList<QString> qcourses;

    // QBarSet 类表示条形图中的一组条形
    QBarSet *set1 = new QBarSet("0~20");
    QBarSet *set2 = new QBarSet("20~40");
    QBarSet *set3 = new QBarSet("40~60");
    QBarSet *set4 = new QBarSet("60~80");
    QBarSet *set5 = new QBarSet("80~100");
    for (auto c : courses)
    {
        qcourses << QString::fromStdString(c->name);
        *set1 << get_ScoreRate(StudentLists[i], c->name, 0, 20);
        *set2 << get_ScoreRate(StudentLists[i], c->name, 20, 40);
        *set3 << get_ScoreRate(StudentLists[i], c->name, 40, 60);
        *set4 << get_ScoreRate(StudentLists[i], c->name, 60, 80);
        *set5 << get_ScoreRate(StudentLists[i], c->name, 80, 100);
    }

    // QPercentBarSeries 类将一系列数据显示为按类别分组的水平条。
    QHorizontalPercentBarSeries *series = new QHorizontalPercentBarSeries();
    series->append(set1);
    series->append(set2);
    series->append(set3);
    series->append(set4);
    series->append(set5);

    // QChart 类管理图表系列(series)、图例(legends)和轴(axes)。
    QChart *chart = ui->qChartRight->chart();             // 获取QChartView自带的chart
    chart->addSeries(series);                             // 将创建好的条形图series添加进chart中
    chart->setTitle("各科各分数层百分比");                // 设置标题
    chart->setAnimationOptions(QChart::SeriesAnimations); // 设置图表变化时的动画效果

    // X轴分类，一般与QBarSet中添加的数据个数相同，如果少了则会显示不全,多了不影响，但是不能重复
    QStringList categories;
    for (auto c : qcourses)
    {
        categories << c;
    }

    // QBarCategoryAxis类向图表的轴添加类别。
    QValueAxis *axisX = new QValueAxis();
    axisX->setTitleText("分数层"); // 设置X轴标题
    axisX->setRange(0, 100);
    chart->addAxis(axisX, Qt::AlignBottom); // 将X轴放在图表的底部
    series->attachAxis(axisX);              // 将axis指定的轴附着到series。

    QBarCategoryAxis *axisY = new QBarCategoryAxis(); // 创建Y轴
    axisY->append(categories);                        // 设置Y轴范围
    axisY->setTitleText("科目");                      // 设置Y轴标题
    chart->addAxis(axisY, Qt::AlignLeft);             // Y轴左对齐
    series->attachAxis(axisY);

    chart->legend()->setVisible(true);             // 设置图例是否可见（默认是可见的）
    chart->legend()->setAlignment(Qt::AlignRight); // 设置图例显示的位置

    ui->qChartRight->setRenderHint(QPainter::Antialiasing); // 设置抗锯齿（不过在条形图中不设置也没关系）
    /*********************绘制各科各分数层百分比条形图*****************/
}

/**
 * @brief 绘制新表格
 * @param tab_
 * @param i
 */
void SIMS::createNewTable(QWidget *tab_, int i)
{
    tab_->setObjectName(QString("tab%1").arg(i));
    QVBoxLayout *verticalLayout_2 = new QVBoxLayout(tab_);
    verticalLayout_2->setObjectName("verticalLayout_2");
    verticalLayout_2->setContentsMargins(8, 8, 8, 8);

    QWidget *centralFrame = new QWidget(tab_);
    centralFrame->setObjectName("centralFrame");

    QVBoxLayout *verticalLayout = new QVBoxLayout(centralFrame);
    verticalLayout->setSpacing(10);
    verticalLayout->setObjectName("verticalLayout");
    verticalLayout->setContentsMargins(0, 5, 0, 0);

    QWidget *topFrame = new QWidget(centralFrame);
    topFrame->setObjectName("topFrame");

    QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(topFrame);
    horizontalLayout_2->setObjectName("horizontalLayout_2");
    horizontalLayout_2->setContentsMargins(0, 0, 0, 0);

    QPushButton *addButton = new QPushButton(topFrame);
    addButton->setObjectName("addButton");
    addButton->setMinimumSize(QSize(0, 35));
    addButton->setMaximumSize(QSize(16777215, 35));
    addButton->setText("添加");

    connect(addButton, &QPushButton::clicked, this, [=]()
            {
        int i = ui->tabWidget->currentIndex();
        AddStudent *addStudentWindow = new AddStudent(tableList[i],StudentLists[i],StuParameters[i]);
        addStudentWindow->getLabStuNum(labStudNum);
        addStudentWindow->show(); });

    QFont font;
    font.setPointSize(12);

    addButton->setFont(font);
    horizontalLayout_2->addWidget(addButton);

    QPushButton *delButton = new QPushButton(topFrame);
    delButton->setObjectName("delButton");
    delButton->setMinimumSize(QSize(0, 35));
    delButton->setMaximumSize(QSize(16777215, 35));
    delButton->setFont(font);
    delButton->setText("删除");

    connect(delButton, &QPushButton::clicked, this, [=]()
            {
        int i = ui->tabWidget->currentIndex();
        int currentRow = tableList[i]->currentRow();
        int id = tableList[i]->item(currentRow,0)->text().toUInt();

        StudentLists[i]->erase(StudentLists[i]->begin()+id);
        tableList[i]->removeRow(currentRow);

        setStatusNum(StudentLists[i]->size()); });

    horizontalLayout_2->addWidget(delButton);

    QPushButton *sumButton = new QPushButton(topFrame);
    sumButton->setObjectName("sumButton");
    sumButton->setMinimumSize(QSize(0, 35));
    sumButton->setMaximumSize(QSize(16777215, 35));
    sumButton->setFont(font);
    sumButton->setText("统计");

    connect(sumButton, &QPushButton::clicked, this, [=]()
            {
        drawPassRateCharts();
        drawScoreRateCharts();
        int i = ui->tabWidget->currentIndex();
        StudentListType *stuList = new StudentListType();
        StudentLists.push_back(stuList);
        ui->tabWidget->addTab(ui->tab_2, QString("tab %1").arg(i+1));
        ui->tabWidget->setCurrentWidget(ui->tab_2); });

    horizontalLayout_2->addWidget(sumButton);

    QToolButton *sortButton = new QToolButton(topFrame);
    sortButton->setObjectName("sortButton");
    sortButton->setMinimumSize(QSize(80, 35));
    sortButton->setMaximumSize(QSize(16777215, 35));
    sortButton->setFont(font);
    sortButton->setPopupMode(QToolButton::MenuButtonPopup);
    sortButton->setArrowType(Qt::NoArrow);
    sortButton->setText("排序");

    connect(sortButton, &QToolButton::clicked, this, [=]()
            { QMessageBox::warning(this, "提示", "请选中列"); });

    horizontalLayout_2->addWidget(sortButton);

    QSpacerItem *horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

    horizontalLayout_2->addItem(horizontalSpacer);

    QFrame *searchframe = new QFrame(topFrame);
    searchframe->setObjectName("searchframe");
    searchframe->setFrameShape(QFrame::StyledPanel);
    searchframe->setFrameShadow(QFrame::Raised);

    QHBoxLayout *horizontalLayout = new QHBoxLayout(searchframe);
    horizontalLayout->setSpacing(0);
    horizontalLayout->setObjectName("horizontalLayout");
    horizontalLayout->setContentsMargins(0, 0, 0, 0);

    QLineEdit *lineEdit = new QLineEdit(searchframe);
    lineEdit->setObjectName("lineEdit");
    lineEdit->setMinimumSize(QSize(0, 35));
    lineEdit->setMaximumSize(QSize(16777215, 35));

    horizontalLayout->addWidget(lineEdit);

    QPushButton *searchButton = new QPushButton(searchframe);
    searchButton->setObjectName("searchButton");
    searchButton->setMinimumSize(QSize(35, 35));
    searchButton->setMaximumSize(QSize(35, 35));
    searchButton->setAutoFillBackground(false);

    QIcon icon1;
    icon1.addFile(QString::fromUtf8(":/res/search.png"), QSize(), QIcon::Normal, QIcon::Off);
    searchButton->setIcon(icon1);
    searchButton->setIconSize(QSize(30, 30));
    searchButton->setCheckable(false);
    searchButton->setAutoExclusive(false);
    searchButton->setAutoDefault(false);
    searchButton->setFlat(false);

    horizontalLayout->addWidget(searchButton);

    horizontalLayout_2->addWidget(searchframe);

    verticalLayout->addWidget(topFrame);

    QTableWidget *tableWidget = new QTableWidget(centralFrame);
    if (tableWidget->columnCount() < 10)
        tableWidget->setColumnCount(10);
    if (tableWidget->rowCount() < 100)
        tableWidget->setRowCount(100);
    tableWidget->setObjectName("tableWidget");
    QFont font1;
    font1.setPointSize(9);
    tableWidget->setFont(font1);
    tableWidget->setAlternatingRowColors(true);
    tableWidget->setSortingEnabled(false);
    tableWidget->setRowCount(100);
    tableWidget->setColumnCount(10);
    tableWidget->setSortingEnabled(true);

    verticalLayout->addWidget(tableWidget);

    verticalLayout_2->addWidget(centralFrame);

    ui->tabWidget->addTab(tab_, QString("tab %1").arg(i));

    tableList << tableWidget;
}

void SIMS::on_action_Add_triggered()
{
    isAddTable = 1;
    QWidget *tab_ = ui->tab_3;
    ui->tabWidget->insertTab(ui->tabWidget->currentIndex() + 1, tab_, QString("添加表格"));
    ui->tabWidget->setCurrentIndex(ui->tabWidget->indexOf(tab_));
}

void SIMS::on_addTable_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(
        this,
        tr("打开文件："),
        "D:/",
        tr("excel files(*.txt *.xls *.xlsx);"));

    if (filePath.isEmpty())
    {
        QMessageBox::warning(this, "Warning!", "Failed to open the file!");
        return;
    }
    else
    {
        if (filePath.contains(".txt")) // 是TXT文件
        {
            // 清空添加界面
            auto i = ui->tabWidget->currentIndex();
            ui->tabWidget->removeTab(i);

            // 创建新标签页
            QWidget *tab_ = new QWidget();
            createNewTable(tab_, i);
            ui->tabWidget->insertTab(ui->tabWidget->currentIndex(), tab_, QString("表格%1").arg(i + 1));
            ui->tabWidget->setCurrentIndex(i);

            // 读取TXT文件、数据预处理、画表格
            readTXT(UnicodetoLocale(filePath));
        }
        else if (filePath.contains(".xls") || filePath.contains(".xlsx")) // 是Excel文件
        {
            // 清空添加界面
            auto i = ui->tabWidget->currentIndex();
            ui->tabWidget->removeTab(i);

            // 创建新标签页
            QWidget *tab_ = new QWidget();
            createNewTable(tab_, i);
            ui->tabWidget->insertTab(ui->tabWidget->currentIndex(), tab_, QString("表格%1").arg(i + 1));
            ui->tabWidget->setCurrentIndex(i);

            // 读取Excel文件、数据预处理、画表格
            readExcel(filePath);
        }
        else
        {
            QMessageBox::warning(this, "Warning!", "TXT/Excel file not found or bad file format!");
            return;
        }
    }
}

void SIMS::on_tabWidget_tabCloseRequested(int index)
{
    ui->tabWidget->removeTab(index);
}

void SIMS::on_actionTXT_2_triggered()
{
    QString _filePath = QFileDialog::getSaveFileName(
        this,
        tr("保存为txt文件："),
        "D:/",
        tr("excel files(*.txt);"));

    std::ofstream outfile(UnicodetoLocale(_filePath), std::ios::out);

    if (!outfile)
    {
        QMessageBox::warning(this, "Error!", "open file failure");
        return;
    }

    int i = ui->tabWidget->currentIndex();
    StudentParameterType *stuParameter = StuParameters[i];

    for (auto &s : *stuParameter)
    {
        outfile << s << " ";
    }

    for (int j = 0; j < tableList[i]->rowCount(); j++)
    {
        outfile << "\n";
        for (int k = 0; k < tableList[i]->columnCount(); k++)
            outfile << tableList[i]->item(j, k)->text().toStdString() << " ";
    }

    outfile << std::endl;

    outfile.close();
}

void SIMS::on_actionBinary_triggered()
{
    QString _filePath = QFileDialog::getSaveFileName(
        this,
        tr("保存为二进制文件："),
        "D:/",
        tr("excel files(*.bin);"));

    std::ofstream outfile(UnicodetoLocale(_filePath), std::ios::out | std::ios::binary);

    if (!outfile)
    {
        QMessageBox::warning(this, "Error!", "open file failure");
        return;
    }

    int i = ui->tabWidget->currentIndex();
    StudentParameterType *stuParameter = StuParameters[i];

    for (auto &s : *stuParameter)
    {
        outfile << s << " ";
    }

    for (int j = 0; j < tableList[i]->rowCount(); j++)
    {
        outfile << "\n";
        for (int k = 0; k < tableList[i]->columnCount(); k++)
            outfile << tableList[i]->item(j, k)->text().toStdString() << " ";
    }

    outfile << std::endl;

    outfile.close();
}

void SIMS::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasUrls() && isAddTable) // 数据中是否包含URL
        event->acceptProposedAction();              // 如果是则接收动作
    else
        event->ignore(); // 否则忽略该事件
}

void SIMS::dropEvent(QDropEvent *event)
{
    const QMimeData *mimeData = event->mimeData(); // 获取MIME数据
    if (mimeData->hasUrls())
    {                                           // 如果数据中包含URL
        QList<QUrl> urlList = mimeData->urls(); // 获取URL列表
        // 将其中第一个URL表示为本地文件路径
        QString fileName = urlList.at(0).toLocalFile();
        if (!fileName.isEmpty())
        {                                  // 如果文件路径不为空
            if (fileName.contains(".txt")) // 是TXT
            {
                // 清空添加界面
                auto i = ui->tabWidget->currentIndex();
                ui->tabWidget->removeTab(i);

                // 创建新标签页
                QWidget *tab_ = new QWidget();
                createNewTable(tab_, i);
                ui->tabWidget->insertTab(ui->tabWidget->currentIndex(), tab_, QString("表格%1").arg(i + 1));
                ui->tabWidget->setCurrentIndex(i);

                // 读取TXT文件、数据预处理、画表格
                readTXT(UnicodetoLocale(fileName));
            }
            else if (fileName.contains(".xls") || fileName.contains(".xlsx")) // 是excel
            {
                // 清空添加界面
                auto i = ui->tabWidget->currentIndex();
                ui->tabWidget->removeTab(i);

                // 创建新标签页
                QWidget *tab_ = new QWidget();
                createNewTable(tab_, i);
                ui->tabWidget->insertTab(ui->tabWidget->currentIndex(), tab_, QString("表格%1").arg(i + 1));
                ui->tabWidget->setCurrentIndex(i);

                // 读取TXT文件、数据预处理、画表格
                readExcel(fileName);
            }
            else
            {
                QMessageBox::warning(this, "Warning!", "TXT/Excel file not found or bad file format!");
                return;
            }
        }
    }
}

void SIMS::on_tabWidget_tabBarClicked(int index)
{
    setStatusNum(StudentLists[index]->size());
}

void SIMS::on_actionExcel_3_triggered()
{
    QString _filePath = QFileDialog::getSaveFileName(
        this,
        tr("保存为xlsx文件："),
        "D:/",
        tr("excel files(*.xlsx);"));

    QAxObject *excel = new QAxObject;
    if (excel->setControl("Excel.Application"))
    {
        excel->dynamicCall("SetVisible (bool Visible)", false);
        excel->setProperty("DisplayAlerts", false);
        QAxObject *workbooks = excel->querySubObject("WorkBooks");     // 获取工作簿集合
        workbooks->dynamicCall("Add");                                 // 新建一个工作簿
        QAxObject *workbook = excel->querySubObject("ActiveWorkBook"); // 获取当前工作簿
        QAxObject *worksheet = workbook->querySubObject("Worksheets(int)", 1);
        QAxObject *cell;
        int h = ui->tabWidget->currentIndex();
        int rowCount = tableList[h]->rowCount();
        int columnCount = tableList[h]->columnCount();

        /*添加Excel表头数据*/
        for (int i = 1; i <= columnCount; i++)
        {
            cell = worksheet->querySubObject("Cells(int,int)", 1, i);
            cell->setProperty("RowHeight", 40);
            cell->dynamicCall("SetValue(const QString&)", tableList[h]->horizontalHeaderItem(i - 1)->data(0).toString());
        }
        /*将form列表中的数据依此保存到Excel文件中*/
        for (int j = 2; j <= rowCount + 1; j++)
        {
            for (int k = 1; k <= tableList[h]->columnCount(); k++)
            {
                cell = worksheet->querySubObject("Cells(int,int)", j, k);
                cell->dynamicCall("SetValue(const QString&)", tableList[h]->item(j - 2, k - 1)->text() + "\t");
            }
        }

        // 以下是批量保存（当数据量较大时可以使用下面的方法，亲测4万个数据可以秒存）
        /*
                QList<QList<QVariant> > datas;
                QVariantList vars;

                for (int i = 2; i <= rowCount + 1; i++)
                {
                    QList<QVariant> row;
                    for(int j = 1; j <= columnCount; j++)
                    {
                        row.append(ui->tableWidget->item(i - 2, j - 1)->text());
                        ui->progressBar->setValue(i);
                    }
                    datas.append(row);
                }

                for(int i=0 ; i<rowCount; i++)
                {
                    vars.append(QVariant(datas[i]));
                }

                QAxObject* range;
                QString asd = "A2:D" + QString::number(rowCount + 1); // A2:D100表示存储范围为A2到D100加1是表头占了一行
                //获取范围
                range = worksheet->querySubObject("Range(const QString&)", asd);
                //批量写入
                //range->dynamicCall("Value2", QVariant(vars));
                range->setProperty("Value2", QVariant(vars));                       //Value: 只支持存为office数据；Value2：支持office和WPS数据

                //设置字体大小
                //range->querySubObject("Font")->setProperty("Size", 30);
                delete range;
        */

        /*将生成的Excel文件保存到指定目录下*/
        workbook->dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(_filePath)); // 保存至fileName
        workbook->dynamicCall("Close()");                                                     // 关闭工作簿
        excel->dynamicCall("Quit()");                                                         // 关闭excel
        delete excel;
        excel = NULL;

        if (QMessageBox::question(NULL, QString::fromUtf8("完成"), QString::fromUtf8("文件已经导出，是否现在打开？"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
        {
            QDesktopServices::openUrl(QUrl("file:///" + QDir::toNativeSeparators(_filePath)));
        }
    }
}
